package com.service.component.user.services.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.service.component.common.CommonResult;
import com.service.component.common.utils.CommonUtils;
import com.service.component.permissions.entity.Permission;
import com.service.component.permissions.mapper.PermissionMapper;
import com.service.component.permissions.services.PermissionService;
import com.service.component.relation.services.RelationServices;
import com.service.component.role.services.RoleServices;
import com.service.component.user.mapper.UserMapper;
import com.service.component.user.entity.Users;
import com.service.component.user.services.UserServices;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.sql.Timestamp;
import java.util.List;
import java.util.Random;

@Service
public class UserServiceImpl implements UserServices {

    @Value("${userno.prefix}")
    private String userNoPrefix;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RelationServices relationServices;

    @Override
    public List<Users> getUser(Users users) {
        return userMapper.selectList(new QueryWrapper<>(users));
    }

    @Override
    public String getUserName(String userId) {
        return userMapper.getUserName(userId);
    }

    @Override
    public CommonResult login(String username, String password) {
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            String passwordToken = String.valueOf(token.getPassword());
            SecurityUtils.getSubject().login(token);
            token.setRememberMe(true);
            Users user = getUserByUsername(username);
            user.setPermissions(relationServices.getUserPermissionByUserId(user.getId()));
            user.setRoles(relationServices.getUserRolesByUserId(user.getId()));
            return CommonResult.success(user);
        } catch (UnknownAccountException e) {
            return CommonResult.commonResult(CommonResult.ResultCode.DATA_NOT_EXIST);
        } catch (IncorrectCredentialsException e) {
            return CommonResult.commonResult(CommonResult.ResultCode.USERNAME_OR_PASSWORD_ERROR);
        }
    }

    @Override
    public Users getUserByUsername(String username) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("USERNAME", username);
        return userMapper.selectOne(queryWrapper);
    }

    @Override
    public Users getUserByUserNo(String userNo) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("USER_NO", userNo);
        return userMapper.selectOne(queryWrapper);
    }

    @Override
    public CommonResult register(Users user) {
        user.setUserNo(getRandomUserNo());
        user.setSalt(new SecureRandomNumberGenerator().nextBytes(CommonUtils.SALT_DIGITS).toString());
        //明文密码进行md5 + salt + hash散列
        Md5Hash md5Hash = new Md5Hash(user.getPassword(), user.getSalt(), 1024);
        user.setPassword(md5Hash.toHex());
        user.setCreatoNo(user.getUserNo());
        user.setModifierNo(user.getUserNo());
        int insert = userMapper.insert(user);
        return insert > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    /**
     * 生成随机的用户编号并且在数据库中不存在
     * @return
     */
    public String getRandomUserNo() {
        //获取当前数据库中最大的用户编号
        String maxUserNo = userMapper.getMaxUserNo();
        //如果存在加1,不存在则从1开始,但编号始终保持6位
        if (StringUtils.isNotEmpty(maxUserNo)) {
            return String.valueOf(Integer.valueOf(maxUserNo)+1);
        }
        return userNoPrefix.concat(String.format("%06d",1));
    }
}
